社会科学ためのDocker入門

レプリケーション駆動な研究のために

August 31, 2023

レプリケーション駆動な研究

なぜ彼のコードは私のPCで動かないのか

バーチャルマシンとレプリケーション

Dockerの利用例

LinuxとDockerの基礎

Linuxとは

  • 狭義: Linuxカーネルのこと
    • OSの基礎的な機能を提供するライブラリ群
  • 広義: Linuxカーネルを採用したOS
    • コマンドやライブラリなどの違いによってディストリビューションに分かれる

Linuxディストリビューション

  • 主にDebian系, RedHat系, その他独立系に分かれる
    • Debian: Ubuntu, Raspberry Pi
    • RedHat: CentOS, Amazon Linux
    • 独立系: Chrome, Android, Arch, Alpine
  • Docker用としてはUbuntuがおすすめ

Dockerの仕組み

Docker コンテナ

  • 1つのマシンのように振る舞う仮想環境
  • ホストOSとカーネルをシェアする
  • ホストもコンテナもLinux OS

仮想化ソフトとの違い

  • 仮想化ソフトはホスト上のソフトウェア
  • ゲストOSをエミュレートして動作する
  • ホストもゲストもLinuxの必要はない
  • 仮想化ソフト上のマシンは遅くなる


イメージとレジストリ

Docker イメージ

  • コンテナの元となるテンプレート
  • USER/IMAGE:TAG で指定する. TAGを省略するとlatestが指定される

Docker レジストリ

  • イメージを保存する場所
  • 基本的にはDocker Hubを用いる.
    • Officialイメージ (ubuntu, rocker, node, jupyter, etc.)
    • 自作イメージをアップロードもできる
  • その他, GitHub Container Registry, Amazon Elastic Container Registry など

VSCode & Docker

なぜVSCodeを使うのか?

  • VSCodeは軽量かつ高機能なエディタ. エディタの現王者といって過言ではない
  • Remote Containersの登場によってDocker環境の導入が革命的に簡単になった

Handson

  1. (Windows) VSCode上で Ctrl-Shift-P を押してWSL: Connect to WSLを選択
  2. ハンズオン用のフォルダを作成. (ファインダー, エクスプローラ, コマンドなど).
  3. VSCodeでフォルダを開く. 左端の のアイコンから
  4. Docker Desktopが起動していることを確認 (のマーク)
  5. VSCodeでCtrl-Shift-Pを押してFrom a predefined...を選択. Ubuntuを選択
    • 残りの選択肢はデフォルトのままでOK
  6. .devcontainer/devcontainer.jsonという設定ファイルが作成される.

Dockerfile

  • 先程のHandsonは既存のUbuntuイメージを利用した
  • 通常は既存のイメージに必要なソフトやパッケージを追加する
  • Dockerfileはその設計図. 拡張子がないことに注意
FROM ubuntu

ENV DEBIAN_FRONTEND noninteractive

RUN apt update && apt install -y curl
  • FROM: ベースとなるイメージを指定
  • ENV: 環境変数を設定. Ubuntuの場合はDEBIAN_FRONTENDはこの設定が必要
  • RUN: シェルコマンドを実行
    • apt update: パッケージリストを更新
    • apt install: パッケージインストール (-y はすべてに自動でyesを返す)

Handson: Remote containers with Dockerfile

  1. VSCodeでCtrl-Shift-Pを押してReopen Folder in WSL/Locallyを選択
  2. .devcontainer/devcontainer.jsonを一度削除する
  3. 以下のDockerfileを作成する
FROM ubuntu

ENV DEBIAN_FRONTEND noninteractive

RUN apt update && apt install -y git
  1. VSCodeでCtrl-Shift-Pを押してReopen in Containerを選択
    • Dockerfileを選択する
  2. ターミナルを開いてユーザー名を確認する (whoami)

ユーザとパーミッション

ユーザ, グループ, Root

  • Linuxではユーザごとにファイルの権限 (読み取り, 書き込み, 実行) が設定されている
  • ユーザはグループに所属する. グループごとに権限を設定することもできる
  • rootユーザ (管理者) はすべてのファイルにアクセスできる

Dockerとユーザ

  • Dockerでは通常, rootユーザでコンテナが起動する
  • Docker上で作業したファイルがroot権限で作成される
  • LinuxとWSL2ユーザーはホスト側からファイルにアクセスできなくなる
  • 一つの解決策として, Dockerfile内でユーザを作成するという方法がある

Handson: Remote Containers with a User

  1. VSCodeでCtrl-Shift-Pを押してReopen Folder in WSL/Locallyを選択
  2. 以下のDockerfileを作成する
FROM ubuntu

ENV DEBIAN_FRONTEND noninteractive

RUN apt update && apt install -y git

ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=$USER_UID

RUN groupadd --gid $USER_GID $USERNAME \
    && useradd --uid $USER_UID --gid $USER_GID -m $USERNAME

USER $USERNAME
  1. .devcontainer/devcontainer.jsonremoteUservscodeに変更する
  2. VSCodeでCtrl-Shift-Pを押してRebuild and Reopen in Containerを選択
  3. ターミナルを開いてユーザー名を確認する (whoami)

on Docker

rockerプロジェクト

  • rockerはオフィシャルのRイメージ群
  • 私はRのライブラリはキャッシュする (後述) ので, rocker/rstudioまたはrocker/geospatialを使うことが多い
  • rstudioというユーザが用意されている
イメージ ベースイメージ 概要
rocker/r-ver ubuntu Ubuntu + R
rocker/rstudio rocker/r-ver + RStudio Server
rocker/tidyverse rocker/rstudio + tidyverse & devtools
rocker/verse rocker/tidyverse + tinytex & 組版関係のパッケージ
rocker/geospatial rocker/geospatial + 地理情報用パッケージ

ポートフォワーディング

通常のRStudio Server

コンテナ内のRStudio Server

  • Docker内のRStudio Serverはホストのブラウザからはアクセスできない
  • ポートフォワーディングを設定することで, ホストのポートをDocker内のポートに接続することができる

マウント

バインドマウント

ボリューム

  • Dockerのコンテナはデフォルトではファイルを保持しない
    • コンテナが削除されるとファイルも削除される
  • バインドマウントはホストのファイルをコンテナにマウントする
  • ボリュームはDockerが管理するファイルをコンテナにマウントする
    • ホスト側からは (基本的に) 見えない
    • コンテナに最適化されたファイルシステムなので, パフォーマンスが良い

docker-compose.yml

  • docker-compose.ymlファイルにコンテナ起動の際の設定を記述することができる
  • 複数のコンテナを起動することもできる
services:
  rstudio:
    build:
      context: .
    environment:
      - TZ=Asia/Tokyo
      - DISABLE_AUTH=true
    volumes:
      - .:/home/rstudio/handson2
  • build context: Dockerfileのパス
  • environment: 環境変数の設定
    • TZ: タイムゾーン
    • DISABLE_AUTH: RStudioのパスワード認証を無効化
  • volumes: マウント
    • HOST_PATH:CONTAINER_PATH
    • 上記の例はバインドマウント

Handson: RStudio Server

  1. 新しいHandson用ののディレクトリを作成する (handson2)
  2. Dockerfileを作成しFROM rocker/rstudioと記述する
  3. 以下のdocker-compose.yml.devcontainer/devcontainer.jsonを作成する
services:
  rstudio:
    build:
      context: .
    environment:
      - TZ=Asia/Tokyo
      - DISABLE_AUTH=true
    volumes:
      - .:/home/rstudio/handson2
{
    "name": "${localWorkspaceFolderBasename}",
    "dockerComposeFile": "../docker-compose.yml",
    "service": "rstudio",
    "remoteUser": "rstudio",
    "forwardPorts": [8787],
    "workspaceFolder": "/home/rstudio/handson2"
}
  1. VSCodeでCtrl-Shift-PからRebuild and Reopen in Containerを選択する
  2. ブラウザでlocalhost:8787にアクセスする

Rパケージのインストール

以下のようなDockerfileでコンテナの中にRパッケージをインストールできる

FROM rocker/rstudio

RUN R -e "install.packages(c('here', 'modelsummary', 'janitor'))"

しかしこの方法はいくつかの問題がある

  • パッケージのバージョンを指定しているわけではない
  • パッケージを追加するごとにDockerfileを書き換える必要がある
  • ビルドのたびにパッケージをインストールするので時間がかかる
  • コンテナごとにパッケージをインストールするのでストレージを圧迫する

これらはrenvのキャッシュをDocker Volumesに保存することで解決できる

Handson: RStudio Server with renv

  1. ホスト側でrenv用のDocker Volumeを作成する
    • docker volume create renv
  2. docker-compose.yml, Dockerfileを以下のように書き換える
    • chownrenvディレクトリの所有者をrstudioにしている
services:
  rstudio:
    build:
      context: .
    environment:
      - TZ=Asia/Tokyo
      - DISABLE_AUTH=true
    volumes:
      - .:/home/rstudio/handson2
      - renv:/home/rstudio/.cache/R/renv

volumes:
  renv:
    external: true      
FROM rocker/rstudio

RUN R -e "install.packages('renv')"

RUN cd /home/rstudio && \
    mkdir .cache .cache/R .cache/R/renv && \
    chown rstudio:rstudio .cache .cache/R .cache/R/renv
  1. VSCodeでCtrl-Shift-PからRebuild and Reopen in Containerを選択する
  2. RStudioでプロジェクト作成し, renvを用いてパッケージを記録する

Docker with VSCode

発展: SSH通信

発展: Git in Docker container

発展: VSCode SSH

発展: Docker on AWS

Practical Guide for Replicable Environment

Docker Desktop for Windows/Mac

DockerはLinux上の技術

  • Docker Desktop for Windows/Macでは, 仮想マシン上のLinuxを用いてDockerを使う
  • WindowsはWSL2という軽量かつ高速なLinuxエミュレータを用いる
  • Mac上のDockerは一般にLinux上のDockerよりも数段遅くなる

ファイルシステムの違い

  • Windows/Mac上のファイルをDocker (Linux) で用いようとするとファイルの変換作業が必要
  • Windowsの場合はWSL2の領域でファイルを保存すれば解決する
  • Macの場合は長らく解決策がなかったが, virtiofsという新しいファイルシステムを用いることで高速化した (らしい)